package com.supreme.securityserver.security;

import com.supreme.securityserver.constants.SecurityConst;
import com.supreme.securityserver.utils.TokenUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class AuthTokenService {

    @Resource
    private RedisTemplate<String, AuthUser> redisTemplate;

    public void refreshToken(AuthUser authUser, Long expiration, TimeUnit timeUnit) {
        authUser.setLoginTime(System.currentTimeMillis());
        authUser.setExpireTime(System.currentTimeMillis() + SecurityConst.JWT_EXPIRATION * 1000);
        String userCode = authUser.getUserCode();
        String tokenKey = TokenUtils.getTokenKey(userCode);
        redisTemplate.opsForValue().set(tokenKey, authUser, expiration, timeUnit);
    }

    public void verifyToken(AuthUser authUser, Long expiration) {
        long expireTime = authUser.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= expiration) {
            this.refreshToken(authUser, expiration, TimeUnit.SECONDS);
        }
    }

    public String generateToken(AuthUser authUser) {
        this.refreshToken(authUser, SecurityConst.JWT_EXPIRATION, TimeUnit.SECONDS);

        Map<String, Object> claims = new HashMap<>();
        claims.put(SecurityConst.JWT_USER_KEY, authUser.getUserCode());
        claims.put("USER_ID", authUser.getUserId());
        return TokenUtils.createToken(SecurityConst.JWT_SUBJECT, claims, SecurityConst.JWT_EXPIRATION);
    }

    public String getToken(HttpServletRequest request) {
        String token = request.getHeader(SecurityConst.AUTHORIZATION);
        if (StringUtils.isNotBlank(token) && token.startsWith(SecurityConst.TOKEN_PREFIX)) {
            token = StringUtils.replace(token, SecurityConst.TOKEN_PREFIX, "");
        }
        return token;
    }

    public AuthUser getLoginUser(String token) {
        if (StringUtils.isNotBlank(token)) {
            Claims claims = TokenUtils.parseToken(token);
            String userKey = (String) claims.get(SecurityConst.JWT_USER_KEY);

            String tokenKey = TokenUtils.getTokenKey(userKey);
            AuthUser authUser = redisTemplate.opsForValue().get(tokenKey);
            return authUser;
        }

        return null;
    }
}
